improved memory wrapper functions
authorØyvind Kolås <ok@src.gnome.org>
Mon, 29 Aug 2005 11:20:15 +0000 (11:20 +0000)
committerØyvind Kolås <ok@src.gnome.org>
Mon, 29 Aug 2005 11:20:15 +0000 (11:20 +0000)
ChangeLog
babl/babl-internal.c
babl/babl-memory.c
babl/babl-memory.h
babl/babl-util.c
babl/babl.c

index bfbd6f13d337ebaea6e2c54d6fd0f05e56e8f5ea..cbc40c4932f03bde53ea1be3ea5dec2493119ef2 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2005-08-29  Øyvind Kolås  <pippin@gimp.org>
+
+       * babl/babl-internal.c: (babl_internal_init): set memory functions.
+       * babl/babl-memory.c: (babl_set_malloc), (babl_set_free),
+       (functions_sanity), (babl_malloc), (babl_free), (babl_realloc),
+       (babl_calloc), (babl_sizeof), (babl_strdup), (babl_strcat),
+       (babl_memory_sanity),
+       * babl/babl-memory.h: Added babl_str* functions, that behave slightly
+       different from the standard ones.
+       * babl/babl-util.c: (babl_add_ptr_to_list): made error fatal.
+       * babl/babl.c: (babl_init), (babl_destroy): added babl_internal
+
 2005-08-28  Øyvind Kolås  <pippin@gimp.org>
 
        * babl/babl-internal.[ch]: (babl_die): A function to call from
index 8eba49141e776c816d3e38d33ba4ac2f8b857212..f19e5b717a7323196180a5bf29ede08e890843d7 100644 (file)
@@ -71,6 +71,8 @@ babl_die (void)
 void
 babl_internal_init (void)
 {
+  babl_set_malloc (malloc);
+  babl_set_free (free);
 }
 
 void
index 3f2b5d4f612e87490e189ff166cece7d026798ab..b4fa769fae955d7e26e5da394cd02bc5e72938b6 100644 (file)
 #include <string.h>
 #include "babl-internal.h"
 
+static void *(* malloc_f) (size_t size) = malloc;
+static void  (* free_f)   (void *ptr)   = free;
+
+static void *first_malloc_used = NULL;
+static void *first_free_used   = NULL;
+
+void
+babl_set_malloc (void *(* malloc_function) (size_t size))
+{
+  malloc_f = malloc_function;
+}
+
+void
+babl_set_free   (void (* free_function) (void *ptr))
+{
+  free_f = free_function;
+}
+
 static char *signature = "So long and thanks for all the fish.";
 
 typedef struct
@@ -36,6 +54,7 @@ typedef struct
 #define BAI(ptr)    ((BablAllocInfo*)(((void*)ptr)-OFFSET))
 #define IS_BAI(ptr) (BAI(ptr)->signature == signature)
 
+/* runtime statistics: */
 static int mallocs  = 0;
 static int frees    = 0;
 static int strdups  = 0;
@@ -52,13 +71,37 @@ mem_stats (void)
   return buf;
 }
 
+static void
+functions_sanity (void)
+{
+  if (first_malloc_used != malloc_f ||
+      first_free_used   != free_f)
+    {
+      if (first_malloc_used == NULL)
+        {
+          first_malloc_used = malloc_f;
+          first_free_used   = free_f;
+        }
+      else
+        {
+          babl_fatal ("babl memory function(s) attempted switched on the fly");
+        }
+    }
+}
+  
+/* Allocate /size/ bytes of memory 
+ *
+ * contents of memory undefined.
+ */
 void *
 babl_malloc (size_t size)
 {
   void *ret;
 
-  assert (size); 
-  ret = malloc (size + OFFSET);
+  assert (size);
+
+  functions_sanity ();
+  ret = malloc_f (size + OFFSET);
   if (!ret)
     babl_log ("args=(%i): failed",  size);
 
@@ -68,21 +111,10 @@ babl_malloc (size_t size)
   return ret + OFFSET;
 }
 
-char *
-babl_strdup (const char *s)
-{
-  char *ret;
-
-  ret = babl_malloc (strlen (s)+1);
-  if (!ret)
-    babl_log ("args=(%s): failed",  s);
-  strcpy (ret, s); 
-
-  strdups++;
-  mallocs--;
-  return ret;
-}
-
+/* Create a duplicate allocation of the same size, note
+ * that the exact location of the allocation needs to be
+ * passed.
+ */
 void *
 babl_dup (void *ptr)
 {
@@ -98,16 +130,23 @@ babl_dup (void *ptr)
   return NULL;
 }
 
+/* Free memory allocated by a babl function (note: babl_free
+ * will complain if memory not allocated by babl is passed.)
+ */
 void
 babl_free (void *ptr)
 {
   if (!ptr)
     return;
   assert(IS_BAI(ptr));
-  free (BAI(ptr));
+  functions_sanity ();
+  free_f (BAI(ptr));
   frees++;
 }
 
+/* reallocate allocation to be in size instead, contents of
+ * common allocated memory between old and new size is preserved.
+ */
 void *
 babl_realloc (void   *ptr,
               size_t  size)
@@ -120,18 +159,32 @@ babl_realloc (void   *ptr,
     }
 
   assert (IS_BAI (ptr));
-  ret = realloc (BAI(ptr), size + OFFSET);
+
+  if (size==0)
+    {
+      babl_free (ptr);
+      return NULL;
+    }
+  if (babl_sizeof (ptr) >= size)
+    {
+      return ptr;
+    }
+  else if (babl_sizeof (ptr) < size)
+    {
+      ret = babl_malloc (size);
+      memcpy (ret, ptr, babl_sizeof (ptr));
+      babl_free (ptr);
+      reallocs++;
+      return ret;
+    }
 
   if (!ret)
-    babl_log ("args=(%p, %i): failed",  ptr, size);
+    babl_fatal ("args=(%p, %i): failed",  ptr, size);
   
-  BAI(ret+OFFSET)->signature = signature;
-  BAI(ret+OFFSET)->size      = size;
-
-  reallocs++;
-  return ret + OFFSET;
+  return NULL;
 }
 
+/* allocate nmemb*size bytes and set it to all zeros. */
 void *
 babl_calloc (size_t nmemb,
              size_t size)
@@ -139,7 +192,7 @@ babl_calloc (size_t nmemb,
   void *ret = babl_malloc (nmemb*size);
 
   if (!ret)
-    babl_log ("args=(%i, %i): failed",  nmemb, size);
+    babl_fatal ("args=(%i, %i): failed",  nmemb, size);
 
   memset (ret, 0, nmemb*size);
 
@@ -148,7 +201,75 @@ babl_calloc (size_t nmemb,
   return ret;
 }
 
-void
+/* Returns the size of an allocation.
+ */
+size_t
+babl_sizeof (void *ptr)
+{
+  assert (IS_BAI (ptr));
+  return BAI(ptr)->size;
+}
+
+/*  duplicate allocation needed for a string, and
+ *  copy string contents, string is zero terminated.
+ */
+char *
+babl_strdup (const char *s)
+{
+  char *ret;
+
+  ret = babl_malloc (strlen (s)+1);
+  if (!ret)
+    babl_log ("args=(%s): failed",  s);
+  strcpy (ret, s); 
+
+  strdups++;
+  mallocs--;
+  return ret;
+}
+
+/* append string to babl allocated string dest, the returned
+ * string is the new canonical position with src added to dest
+ * if the dest allocation needed to be resized. Passing NULL
+ * causes a new allocation (thus babl-memory sees NULL as the empty
+ * string).
+ */
+char *
+babl_strcat (char       *dest,
+             const char *src)
+{
+  char *ret;
+  int src_len;
+  int dst_len;
+
+  src_len = strlen (src);
+  if (!dest)
+    {
+      ret = babl_malloc (src_len+1);
+      strcpy (ret, src);
+      return ret;
+    }
+  assert (IS_BAI (dest));
+  dst_len = strlen (dest);
+  
+  ret = dest;
+
+  if (babl_sizeof (dest) < src_len + dst_len + 1)
+    {
+      size_t new_size = babl_sizeof (dest);
+      while (new_size < src_len + dst_len + 1)
+        new_size*=2;
+      ret = babl_realloc (dest, new_size);
+    }
+
+  strcpy (&ret[dst_len], src);
+  return ret;
+}
+
+/* performs a sanity check on memory, (checks if number of
+ * allocations and frees on babl memory evens out to zero).
+ */
+int
 babl_memory_sanity (void)
 {
   if (frees != mallocs + strdups + callocs)
@@ -157,5 +278,7 @@ babl_memory_sanity (void)
 "%s\n"
 "\tbalance: %i-%i=%i\n",
   mem_stats(), (strdups+mallocs+callocs),frees, (strdups+mallocs+callocs)-frees);
+      return -1;
     }
+  return 0;
 }
index 6465b918449e6c6007f9ad960a31847a57acace9..170e5662c62e4031b310d865ff5d916c6cba2c87 100644 (file)
 #ifndef _BABL_MEMORY_H
 #define _BABL_MEMORY_H
 
-void * babl_malloc          (size_t        size);
-void   babl_free            (void         *ptr);
+void   babl_set_malloc    (void     *(*malloc_function) (size_t  size));
+void   babl_set_free      (void      (*free)            (void   *ptr));
+int    babl_memory_sanity (void);
 
-void * babl_realloc         (void         *ptr,
-                             size_t        size);
+void * babl_malloc        (size_t      size);
+void   babl_free          (void       *ptr);
+void * babl_calloc        (size_t      nmemb,
+                           size_t      size);
+void * babl_realloc       (void       *ptr,
+                           size_t      size);
+
+size_t babl_sizeof        (void       *ptr);
+void * babl_dup           (void       *ptr);
+
+char * babl_strdup        (const char *s);
+char * babl_strcat        (char       *dest,
+                           const char *src);
 
-void * babl_calloc          (size_t        nmemb,
-                             size_t        size);
-char * babl_strdup          (const char   *s);
-void * babl_dup             (void         *ptr);
-void   babl_memory_sanity   (void);
 
 #endif
index 3d40fe868500034af1379731edd6d4e40895ad7f..8df5839a482e720cd7e0d8f61df367322da25ca0 100644 (file)
@@ -53,7 +53,7 @@ babl_add_ptr_to_list (void ***list,
 
   if (!(*list))
     {
-       babl_log ("failed to realloc");
+       babl_fatal ("failed to realloc");
     }
 
   (*list)[orig_len]=new;
index d6573266893e089bd7fc0e4ce486a6f6643a300f..3d0dd1d0f2d04d120c9d13425a220aff44af30ad 100644 (file)
@@ -30,6 +30,7 @@ babl_init (void)
 {
   if (ref_count++==0)
     {
+      babl_internal_init ();
       babl_type_init ();
       babl_sampling_init ();
       babl_component_init ();
@@ -58,6 +59,7 @@ babl_destroy (void)
       babl_component_destroy ();
       babl_sampling_destroy ();
       babl_type_destroy ();
+      babl_internal_destroy ();
       babl_memory_sanity ();
     }
 }